package org.atlantis.grosbeak.depot.loader;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.atlantis.grosbeak.depot.DepotException;
import org.atlantis.grosbeak.json.JsonException;
import org.atlantis.grosbeak.json.Jsons;
import org.atlantis.grosbeak.lang.Exceptions;
import org.atlantis.grosbeak.lang.Files;

/**
 * 通过Json配置文件来加载对象。此类会把Json配置文件解析成一个Map，然后把这个
 * Map交给MapLoader来解析。即：JsonLoader不去从配置文件中解析出对象，它只是
 * 把Json配置文件通过Jsons转换成一个Map，然后把这个Map交给MapLoader，让MapLoader 从中解析出对象。
 * 
 * @author <a href="mailto:seenoevil.cn@gmail.com">SeeNoEvil</a>
 * 
 */
public class JsonLoader extends MapLoader {

	public static enum ENCODING {
		UTF8, GBK, ISO88591, GB2312, BIG5;

		private String getEncoding(ENCODING enc) {
			switch (enc) {
			case UTF8:
				return "UTF-8";
			case GBK:
				return "GBK";
			case ISO88591:
				return "ISO-8859-1";
			case GB2312:
				return "GB2312";
			case BIG5:
				return "BIG5";
			default:
				return "UTF-8";
			}
		}
	}

	/**
	 * 实例化一个JsonLoader。
	 * 
	 * @param files
	 *            Json配置文件的路径（可有多个Json配置文件） - 默认以UTF-8编码读取配置文件。
	 */
	public JsonLoader(String... files) {
		this(ENCODING.UTF8, files);
	}

	/**
	 * 实例化一个JsonLoader。
	 * 
	 * @param encoding
	 *            读取Json配置文件所使用的编码。
	 * @param files
	 *            Json配置文件的路劲（可有多个Json配置文件）。
	 */
	public JsonLoader(ENCODING encoding, String... files) {
		Map<String, Map<String, Object>> map = new HashMap<String, Map<String, Object>>();
		for (String path : files) {
			File file = Files.find(path);
			if (null == file)
				throw Exceptions.makeThrow(DepotException.class,
						"Unable to find file '%s'.", path);
			map.putAll(jsonToMap(file, encoding.getEncoding(encoding)));
		}
		this.setMap(map);
	}

	// 通过Jsons把Json信息转换成一个Map。
	@SuppressWarnings("unchecked")
	private Map<String, Map<String, Object>> jsonToMap(File file,
			String encoding) {
		try {
			return Jsons.fromJson(Map.class, Files.readFileToString(file,
					encoding));
		} catch (JsonException e) {
			throw Exceptions.makeThrow(DepotException.class, e,
					"The json configuration file '%s' Error.", file);
		}
	}
}
